package com.owc.service.impl.admin;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.owc.common.enums.FlowTypeEnum;
import com.owc.common.enums.StatusEnum;
import com.owc.common.tool.BeanUtils;
import com.owc.common.tool.DateUtils;
import com.owc.common.tool.UtilsService;
import com.owc.dao.AccountFlowMapper;
import com.owc.domain.BaseResult;
import com.owc.domain.dto.BalanceDTO;
import com.owc.domain.dto.BannerDTO;
import com.owc.domain.dto.DetailBean;
import com.owc.domain.dto.admin.AccountFlowDTO;
import com.owc.domain.entity.AccountFlow;
import com.owc.domain.entity.User;
import com.owc.domain.vo.admin.AccountFlowVo;
import com.owc.domain.vo.app.TokenDetailVo;
import com.owc.domain.vo.app.TokenVo;
import com.owc.service.admin.AccountFlowService;
import com.owc.service.admin.UserManageService;
import com.owc.service.app.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @Author Jackies
 * @Date 2019/12/26 22:08
 * @Description TODO://
 **/
@Service
@Slf4j
public class AccountFlowServiceImpl implements AccountFlowService {

	@Resource
	private AccountFlowMapper accountFlowMapper;
	@Autowired
	private UserService userService;
	@Autowired
	private UserManageService userManageService;

	@Override
	public boolean insertFlow(FlowTypeEnum flowTypeEnum, Long userId, BigDecimal transferAmount,
							  String address, Long tokenId, String transferId, String txHash, StatusEnum statusEnum) throws Exception {

		Optional<User> optionalUser = userService.selectById(userId);
		if(!optionalUser.isPresent()){
			log.error("记录流水信息失败,因为userId:[{}]不存在",userId);
			return false;
		}
		//这儿表明,当address为Null时,这说明这是平台级别的流水,则需要将UserId设置为-1L,便于自动获取平台余额
		if(address == null) {
			userId = -1L;
		}

		//获取钱包余额
		BalanceDTO accountBalance = getAccountWalletBalance(userId,flowTypeEnum,tokenId,"wallet");
		//获取账户余额
		BalanceDTO balance = getAccountWalletBalance(userId,flowTypeEnum,tokenId,"balance");

		String[] fields = {"userId","userPhone","amount","type","address","commitTime","tokenId","tokenName","transferId","walletBalance","balance","txId","status"};
		Object[] values = {userId,optionalUser.get().getPhone(),transferAmount,flowTypeEnum.getType(),address,
				DateUtils.formatYMDHMS(new Date()),tokenId,accountBalance.getTokenName(),transferId,
				accountBalance.getBalance(),balance.getBalance(),txHash, statusEnum.getType()};

		try {
			AccountFlow accountFlow = BeanUtils.buildDefaultAttrModel(fields,values,AccountFlow.class);
			accountFlowMapper.insert(accountFlow);
			return true;
		} catch (Exception e) {
			log.error("保存流水信息失败 message:[{}]",e.getMessage());
			throw new RuntimeException(e.getMessage());
		}
	}

	@Override
	public boolean insertFlow(FlowTypeEnum flowTypeEnum, Long userId, BigDecimal transferAmount,
	                          String address, Long tokenId, String transferId,String txHash) throws Exception {

		return insertFlow(flowTypeEnum, userId, transferAmount, address, tokenId, transferId, txHash,StatusEnum.SUCCESS);
	}

	@Override
	public BaseResult<List<AccountFlowDTO>> list(AccountFlowVo accountFlowVo) {
		PageHelper.startPage(accountFlowVo.getPageIndex(),accountFlowVo.getPageSize());
		List<AccountFlowDTO> accountFlowDTOS = accountFlowMapper.selectByQueryModel(accountFlowVo);
		PageInfo<AccountFlowDTO> pageInfo = new PageInfo<>(accountFlowDTOS);
		return BaseResult.success(accountFlowDTOS,pageInfo.getTotal());
	}

	@Override
	public PageInfo<DetailBean> getUserFlowList(Long userId, TokenDetailVo vo) {
		PageHelper.startPage(vo.getPageIndex(),vo.getPageSize());
		List<DetailBean> list = accountFlowMapper.selectUserFlowList(userId,vo.getType(),vo.getId());
		return new PageInfo<>(list);
	}

	@Override
	public void updateFlowStatus(String transferId, StatusEnum refuse) {
		AccountFlow accountFlow = new AccountFlow();
		accountFlow.setTransferId(transferId);
		accountFlow.setStatus(refuse.getType());
		accountFlowMapper.updateStatusByTransferId(accountFlow);
	}

	@Override
	public void updateFlowInfo(AccountFlow accountFlow) {
		Assert.notNull(accountFlow.getFlowId(),"Update flow info. FlowId must nit be null");
		accountFlowMapper.updateByPrimaryKeySelective(accountFlow);
	}

	@Override
	public AccountFlow getFlowByTransferId(String transferId) {
		return accountFlowMapper.selectByTransferId(transferId);
	}

	@Override
	public void updateFlowInfoByTransferId(AccountFlow accountFlow) {
		Assert.notNull(accountFlow.getTransferId(),"Update flow info. transferId must nit be null");
		accountFlowMapper.updateByTransferId(accountFlow);
	}

	private BalanceDTO getAccountWalletBalance(Long userId, FlowTypeEnum flowTypeEnum, Long tokenId, String type) throws Exception {
		if("wallet".equals(type)) {
			return userManageService.getWalletBalance(new TokenVo(tokenId, userId));
		}
		//当流水为矿工费,平台转出,平台转入时,不需要保存账户余额
		switch (flowTypeEnum){
			case recharge:
			case withdraw:
			case withdrawCost:
			case withdrawRefuseBack:
			case withdrawRefuseCostBack:
			case drawIn:
			case drawOut:
			case exchange:
			case lock:
			case redemption:
			case INCOME:
				return new BalanceDTO(userService.selectBalanceByUserId(userId, tokenId),null);
		}
		return new BalanceDTO();
	}
}
